package org.example;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 哔哩哔哩视频解析器
 * 用于从哔哩哔哩视频URL中提取音频信息
 */
public class BilibiliParser {
    private static final Logger logger = LoggerFactory.getLogger(BilibiliParser.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    // 哔哩哔哩视频URL的正则表达式
    private static final Pattern BILIBILI_URL_PATTERN = Pattern.compile(
        "https?://(?:www\\.)?bilibili\\.com/video/([A-Za-z0-9]+)"
    );
    
    // 哔哩哔哩API接口
    private static final String BILIBILI_API_URL = "https://api.bilibili.com/x/web-interface/view";
    
    /**
     * 从哔哩哔哩URL中提取视频ID
     * @param url 哔哩哔哩视频URL
     * @return 视频ID，如果无法提取则返回null
     */
    public String extractVideoId(String url) {
        if (url == null || url.trim().isEmpty()) {
            logger.warn("URL为空");
            return null;
        }
        
        Matcher matcher = BILIBILI_URL_PATTERN.matcher(url);
        if (matcher.find()) {
            String videoId = matcher.group(1);
            logger.info("成功提取视频ID: {}", videoId);
            return videoId;
        } else {
            logger.warn("无法从URL中提取视频ID: {}", url);
            return null;
        }
    }
    
    /**
     * 获取视频信息
     * @param videoId 视频ID
     * @return 视频信息对象
     * @throws IOException 网络请求异常
     */
    public VideoInfo getVideoInfo(String videoId) throws IOException {
        if (videoId == null || videoId.trim().isEmpty()) {
            throw new IllegalArgumentException("视频ID不能为空");
        }
        
        String apiUrl = BILIBILI_API_URL + "?bvid=" + videoId;
        logger.info("请求视频信息: {}", apiUrl);
        
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(apiUrl);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            httpGet.setHeader("Referer", "https://www.bilibili.com");
            
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                String responseBody = EntityUtils.toString(entity);
                
                logger.debug("API响应: {}", responseBody);
                
                JsonNode rootNode = objectMapper.readTree(responseBody);
                
                if (rootNode.get("code").asInt() != 0) {
                    throw new IOException("API请求失败: " + rootNode.get("message").asText());
                }
                
                JsonNode dataNode = rootNode.get("data");
                VideoInfo videoInfo = new VideoInfo();
                videoInfo.setBvid(dataNode.get("bvid").asText());
                videoInfo.setTitle(dataNode.get("title").asText());
                videoInfo.setDescription(dataNode.get("desc").asText());
                videoInfo.setDuration(dataNode.get("duration").asLong());
                videoInfo.setCid(dataNode.get("cid").asLong());
                
                logger.info("成功获取视频信息: {}", videoInfo.getTitle());
                return videoInfo;
            }
        }
    }
    
    /**
     * 获取音频URL
     * @param videoId 视频ID
     * @return 音频URL
     * @throws IOException 网络请求异常
     */
    public String getAudioUrl(String videoId) throws IOException {
        VideoInfo videoInfo = getVideoInfo(videoId);
        if (videoInfo == null) {
            throw new IOException("无法获取视频信息");
        }
        
        // 这里需要调用哔哩哔哩的播放API来获取实际的音频URL
        // 由于哔哩哔哩的API可能会变化，这里提供一个基础实现
        String playUrl = String.format("https://api.bilibili.com/x/player/playurl?bvid=%s&cid=%d&qn=80&fnval=16", 
                                     videoInfo.getBvid(), videoInfo.getCid());
        
        logger.info("获取播放URL: {}", playUrl);
        
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(playUrl);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            httpGet.setHeader("Referer", "https://www.bilibili.com");
            
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                String responseBody = EntityUtils.toString(entity);
                
                JsonNode rootNode = objectMapper.readTree(responseBody);
                
                if (rootNode.get("code").asInt() != 0) {
                    throw new IOException("获取播放URL失败: " + rootNode.get("message").asText());
                }
                
                JsonNode dataNode = rootNode.get("data");
                JsonNode dashNode = dataNode.get("dash");
                
                if (dashNode != null && dashNode.has("audio")) {
                    JsonNode audioNode = dashNode.get("audio").get(0);
                    String audioUrl = audioNode.get("baseUrl").asText();
                    logger.info("成功获取音频URL");
                    return audioUrl;
                } else {
                    throw new IOException("无法获取音频URL");
                }
            }
        }
    }
    
    /**
     * 视频信息类
     */
    public static class VideoInfo {
        private String bvid;
        private String title;
        private String description;
        private long duration;
        private long cid;
        
        // Getters and Setters
        public String getBvid() { return bvid; }
        public void setBvid(String bvid) { this.bvid = bvid; }
        
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public long getDuration() { return duration; }
        public void setDuration(long duration) { this.duration = duration; }
        
        public long getCid() { return cid; }
        public void setCid(long cid) { this.cid = cid; }
        
        @Override
        public String toString() {
            return "VideoInfo{" +
                    "bvid='" + bvid + '\'' +
                    ", title='" + title + '\'' +
                    ", duration=" + duration +
                    ", cid=" + cid +
                    '}';
        }
    }
} 